#include <cstdio>
#include <glad/glad.h>
#include <SDL2/SDL.h>

#include "shader/TextureLearningShader.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stbImage/stb_image.h>

int main(int argc, char** argv)
{
    const int windowWidth = 600;
    const int windowHeight = 600;
    // 设置 SQL 版本和信息
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
    SDL_Init(SDL_INIT_EVERYTHING);

    if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
    {
        printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError());
        return -1;
    }
    atexit(SDL_Quit);
    SDL_Window* window = SDL_CreateWindow("SDL 窗口", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, windowWidth, windowHeight, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    if(window == nullptr)
    {
        printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
        return -1;
    }
    SDL_GL_CreateContext(window);
    SDL_GL_SetSwapInterval(1);
    //注册OpenGL函数指针
    if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
    {
        printf("Failed to Load GL Loader for glad!");
        return -1;
    }

    // 每个顶点由8个float组成, 由332分为三个属性, 分别为画布位置xyz, 颜色值rgb, 纹理采样位置st
    float vertices[] = {
            0.5f,  0.5f, 0.0f,  1.0f, 1.0f,   // 右上
            0.5f, -0.5f, 0.0f,  1.0f, 0.0f,   // 右下
            -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,   // 左下
            -0.5f,  0.5f, 0.0f, 0.0f, 1.0f    // 左上
    };
    unsigned int indices[] = {
            0, 1, 3, // 第一个三角形
            1, 2, 3  // 第二个三角形
    };

    uint32_t VAO = 0;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    uint32_t VBO = 0;
    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    uint32_t EBO = 0;
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)nullptr);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    // 加载图形
    int width = 0, height = 0, channels = 0;
    uint8_t* data = stbi_load("bits/test.png", &width, &height, &channels, 0);

    printf("image loaded.\nw: %d, h: %d, c: %d\n", width, height, channels);

    glActiveTexture(GL_TEXTURE0);
	// 创建纹理对象并绑定
	uint32_t textureId;
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);
    // 设置纹理延伸方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    // 设置纹理采样方法
    // MIPMAP是多级渐远纹理采样方法
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	// 创建纹理
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
	// 创建多级渐远纹理
	glGenerateMipmap(GL_TEXTURE_2D);

    // 释放图形内存
    stbi_image_free(data);

    glActiveTexture(GL_TEXTURE1);
    int width2 = 0, height2 = 0, channels2 = 0;
    uint8_t* data2 = stbi_load("bits/test.jpeg", &width2, &height2, &channels2, 0);
    printf("image2 loaded.\nw: %d, h: %d, c: %d\n", width2, height2, channels2);
    uint32_t textureId2;
    glGenTextures(1, &textureId2);
    glBindTexture(GL_TEXTURE_2D, textureId2);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width2, height2, 0, GL_RGB, GL_UNSIGNED_BYTE, data2);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data2);

    TextureLearningShader shader;
    int32_t counter = 0;

    glEnable(GL_DEPTH_TEST);
    bool runFlag = true;
    SDL_Event event;

    //渲染循环
    while(runFlag)
    {
        //处理键盘事件
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT)
                runFlag = false;
        }

        glClearColor(0.22f, 0.33f, 0.33f, 0.5f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        counter++;
        counter %= 100;
        float value = fabs(counter - 50) / 50.0f;

        shader.UseShader();
        shader.setFloat("d", value);
        shader.setInt("tex", 0);
        shader.setInt("tex2", 1);
        glBindVertexArray(VAO);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

        SDL_GL_SwapWindow(window);
        SDL_Delay(33);
    }

    SDL_DestroyWindow(window);
    return 0;
}
